﻿#region Copyright(C) 2010-2010 NCS Pte. Ltd. All rights reserved.
// ==================================================================================================
// Copyright(C) 2010 NCS Pte. Ltd. All rights reserved.
//
// SYSTEM NAME	    : iConnect .Net Application Framework
// COMPONENT ID	    : CBEC.Core.Wcf
// COMPONENT DESC   : Core components for WCF.	
//
// CREATED DATE/BY  : 18 Aug 2010 / Gao Ye
//
// REVISION HISTORY :	
// DATE/BY			SR#/CS/PM#/OTHERS		DESCRIPTION OF CHANGE
// ==================================================================================================
#endregion

using CBEC.Core.Configuration;
using CBEC.Core.Wcf.Properties;
using System;
using System.ComponentModel;
using System.Configuration;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;

namespace CBEC.Core.Wcf.Compression.Configuration
{
    /// <summary>
    /// The <see cref="CompressedTextMessageEncodingBindingElement"/> specific <see cref="BindingElementExtensionElement"/>.
    /// </summary>
    public class CompressedTextMessageEncodingConfigurationElement : BindingElementExtensionElement
    {
        private const string TextEncodingPropertyName = "textEncoding";
        private const string CompressAlgorithmPropertyName = "compressAlgorithm";
        private const string MinMessageSizePropertyName = "minMessageSize";
        private const string CustomCompressorTypePropertyName = "customCompressorType";

        /// <summary>
        /// Gets or sets the text encoding.
        /// </summary>
        /// <value>
        /// The text encoding.
        /// </value>
        [ConfigurationProperty(TextEncodingPropertyName)]
        public TextMessageEncodingElement TextEncoding
        {
            get { return (TextMessageEncodingElement)this[TextEncodingPropertyName]; }
            set { this[TextEncodingPropertyName] = value; }
        }

        /// <summary>
        /// Gets or sets the compress algorithm.
        /// </summary>
        /// <value>
        /// The compress algorithm.
        /// </value>
        [ConfigurationProperty(CompressAlgorithmPropertyName, IsRequired = false, DefaultValue = CompressAlgorithm.GZip)]
        public CompressAlgorithm CompressAlgorithm
        {
            get { return (CompressAlgorithm)this[CompressAlgorithmPropertyName]; }
            set { this[CompressAlgorithmPropertyName] = value; }
        }

        /// <summary>
        /// Gets or sets the type of the custom compressor.
        /// </summary>
        /// <value>
        /// The type of the custom compressor.
        /// </value>
        [ConfigurationProperty(CustomCompressorTypePropertyName, IsRequired = false, DefaultValue = null)]
        [TypeConverter(typeof(AssemblyQualifiedTypeNameConfigurationConverter))]
        public Type CustomCompressorType
        {
            get { return (Type)this[CustomCompressorTypePropertyName]; }
            set { this[CustomCompressorTypePropertyName] = value; }
        }

        /// <summary>
        /// When overridden in a derived class, gets the <see cref="T:System.Type"/> object that represents the custom binding element.
        /// </summary>
        /// <returns>A <see cref="T:System.Type"/> object that represents the custom binding type.</returns>
        public override Type BindingElementType
        {
            get { return typeof(CompressedTextMessageEncodingBindingElement); }
        }

        /// <summary>
        /// When overridden in a derived class, returns a custom binding element object.
        /// </summary>
        /// <returns>
        /// A custom <see cref="T:System.ServiceModel.Channels.BindingElement"/> object.
        /// </returns>
        protected override BindingElement CreateBindingElement()
        {
            TextMessageEncodingBindingElement innerBindingElement = new TextMessageEncodingBindingElement();
            if (null != this.TextEncoding)
            {
                this.TextEncoding.ApplyConfiguration(innerBindingElement);
            }

            Compressor compressor = null;
            switch (this.CompressAlgorithm)
            {
                case Compression.CompressAlgorithm.GZip:
                    {
                        compressor = new GZipCompressor();
                        break;
                    }
                case Compression.CompressAlgorithm.Deflat:
                    {
                        compressor = new DeflateCompressor();
                        break;
                    }
                case Compression.CompressAlgorithm.Custom:
                    {
                        if (null == this.CustomCompressorType)
                        {
                            throw new ConfigurationErrorsException(Resources.ExceptionMissCustomCompressorType);
                        }
                        if (null == this.CustomCompressorType.GetConstructor(Type.EmptyTypes))
                        {
                            throw new ConfigurationErrorsException(ResourceUtility.Format(Resources.ExceptionTypeHasNoContructor, this.CustomCompressorType.AssemblyQualifiedName));
                        }
                        if (!typeof(Compressor).IsAssignableFrom(this.CustomCompressorType))
                        {
                            throw new ConfigurationErrorsException(ResourceUtility.Format(Resources.ExceptionNotValideCompressor, this.CustomCompressorType.AssemblyQualifiedName));
                        }
                        compressor = (Compressor)Activator.CreateInstance(this.CustomCompressorType);
                        break;
                    }
            }

            return new CompressedTextMessageEncodingBindingElement(innerBindingElement, compressor);
        }
    }
}